package com.gopay.common.trace.helper;

import com.gopay.common.trace.anotation.GopayTracer;
import com.gopay.common.trace.def.BinaryAnnotation;
import com.gopay.common.trace.def.Tracer;
import com.gopay.common.trace.enums.TraceType;
import com.gopay.common.trace.support.GenTraceId;
import com.gopay.common.trace.util.GopayTracerUtil;
import org.apache.commons.lang3.StringUtils;
import org.aspectj.lang.JoinPoint;

import java.lang.reflect.Method;
import java.util.ArrayList;
import java.util.List;

/**
 * @author ddh02
 * @LocalLogHelper
 * @2017/5/18 15:39  www.gopay.com.cn Inc.All rights reserved.
 */
public class LogLocalHelper extends LogAbstractHelper {

    private boolean isMultiThread = false;

    @Override
    public void before(Object... args) {

        try {
            JoinPoint joinPoint = (JoinPoint) args[0];
            GopayTracer gopayTracer = (GopayTracer) args[1];

            if (StringUtils.isBlank(tid)) {
                //没有 源头调用链  不做采集 ===>>后续 需要处理 多线程的情况 =====》》》TODO

                //如果 可能是多线程
                if (gopayTracer.multipleThread()) {
                    tid = GenTraceId.genUUID();
                    logContext.setTid(tid);
                    isMultiThread = true;
                } else {
                    return;
                }
            }

            spanName  = joinPoint.getTarget().getClass().getSimpleName() + "." + joinPoint.getSignature().getName();

            count = logContext.incrCount();//当前线程计数加一
            ps = logContext.getSpan(count - 1); //获取父span

            //本地方法 如果没有父 并且没有tid ， 则 不做处理
            /*if (StringUtils.isBlank(tid) && ps == null) {
                setIsExecute(false);
                return;
            }*/
           // span = Tracer.getTracer().newSpan(spanName, TraceType.LOCAL, false);

            span = Tracer.getTracer().genSpan(tid, spanName, TraceType.LOCAL);

            //--多线程 暂时屏蔽掉
            /*if (threadName.toLowerCase().indexOf("thread") != -1
                    || threadName.toLowerCase().indexOf("pool") != -1){
                isMultiThread = true;
            }*/

            /*if (StringUtils.isNotBlank(tid)) {
                span.setTid(tid);
            } *//*else if (isMultiThread) {
                tid = GenTraceId.genUUID();
                logContext.setTid(tid);
                span.setTid(tid);

                //如果是 多线程 访问  没有tid话 首次 生成一个tid
            }*/

            /*
             * add by zyt,2017-12-6,对传过来类似于gopayorderId之类的字段，存储于baList，并设置到span中
             */

            //处理订单
            if (gopayTracer != null && StringUtils.isNotBlank(gopayTracer.orderIdSpel())) {
                Object fieldValue = GopayTracerUtil.getSpelValue(gopayTracer.orderIdSpel(), joinPoint);
                if(fieldValue != null && fieldValue instanceof String ){
                    span.setOid((String) fieldValue);
                }
            }

            //处理 其他 附加 信息
            if(gopayTracer != null && StringUtils.isNotBlank(gopayTracer.paramKey())){
                Object fieldValue = GopayTracerUtil.getSpelValue(gopayTracer.paramKey(), joinPoint);
                if(fieldValue != null){
                    BinaryAnnotation ba = new BinaryAnnotation();
                    ba.setKey("spel");
                    ba.setType(getTraceType().name());
                    ba.setValue(fieldValue.toString());
                    span.addBinaryAnnotation(ba);
                }
            }

            //生成ss
            tracer.serverReceive(span, null, startTime);

            //设置到map中
            logContext.setSpan(count, span);

        } catch (Exception e) {
            printSelfException(e, "local method before 阶段自身异常！");
        }

    }

    @Override
    public void after(Object... args) {

        if (!isExecute) {
            return;
        }

        long end = System.currentTimeMillis();

        try {

            if (StringUtils.isBlank(tid)) {
               /* if (SamplingUtils.isSelected()) {
                    TraceLogUtils.log(new TraceLog(TraceType.LOCAL, end - startTime, span));
                }
                span = null;*/
                return;  //返回
            }

            JoinPoint joinpoint = (JoinPoint) args[0];
            //执行完后 线程计数减一
            logContext.dncrCount();


            tracer.serverSend(span, null, end);

            if (ps != null) {

                ps.addChild(span);

                /*if (isMultiThread) {
                    if (spanName.equals("MerNotifyImpl.send")) {
                        try {
                            Object o = joinpoint.getArgs()[0];
                            if (o != null) {
                                String orderId = ReflectionUtil.getProperty4String(o, "orderId");
                                addBa("order", "notify.orderId", orderId, span);
                            }
                        } catch (Exception e) {
                            e.printStackTrace();
                        }
                    }
                }*/
            } else {
                if (isMultiThread) {
                    //多线程 并且 父为空 说明是 多线程调用的 首次调用， 所以 应该 进行打印输出
                    tracer.serverSend(span, null, end);
                    tracer.endAndShow(span);
                    return;
                }
                span = null;
            }

        } catch (Exception e) {
            printSelfException(e, "httpclient after 阶段自身异常！");
        }
    }

    @Override
    public void ex(Throwable throwable) {
        commonProcessEx(throwable);
    }

    @Override
    public TraceType getTraceType() {
        return TraceType.LOCAL;
    }
}
